package tech.dingxin;


import com.google.protobuf.ByteString;
import com.google.protobuf.MessageLite;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import tech.dingxin.codec.GzipUtils;
import tech.dingxin.protobuf.frame;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;

/**
 * @author dingxin
 */
public class Server {

    /**
     * 端口号
     */
    private final int port;

    public Server(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws Exception {
        //调用服务器的start()方法
        new Server(10010).start();
    }


    public void start() throws Exception {
        //配置NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //服务器辅助启动类配置
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new ProtobufVarint32FrameDecoder());
                            pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
                            pipeline.addLast(new ProtobufEncoder());
                            pipeline.addLast(new ProtobufDecoder(frame.Frame.getDefaultInstance()));
                            pipeline.addLast(new ObjectHandler());
                        }
                    })
                    //禁止使用Nagle算法，使用于小数据即时传输
                    .option(ChannelOption.TCP_NODELAY, true)
                    //设置tcp缓冲区
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //允许长连接
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            /** 异步的绑定服务器，调用sync()方法阻塞等待直到绑定完成 */
            ChannelFuture f = b.bind().sync();
            //等待服务端监听端口关闭
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static final class ObjectHandler extends SimpleChannelInboundHandler {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
            frame.Frame req = (frame.Frame) msg;

//            // 进行图片资源的还原
//            //byte[] attachment = GzipUtils.ungzip(req.getDataList());
//
//            // 获取图片的保存目录
//            String path = System.getProperty("user.dir") + File.separatorChar
//                    + "receive" + File.separatorChar + req.getName();
//            // 进行图片的保存
//            FileOutputStream fos = new FileOutputStream(path);
//            fos.write(attachment);
            //fos.close();
        }
    }
}



